import { FC, useEffect, useState, useRef, useMemo } from 'react';
import { QuestionCard, QuestionSearch } from '@/components';
import styles from '@/assets/css/Common.module.scss';
import { Typography, Spin, Empty } from 'antd';
import { useSearchParams } from 'react-router-dom';
import { useDebounceFn, useRequest } from 'ahooks';
import { getAllQuestionList } from '@/services/question';
import { LIST_PAGE_SIZE, LIST_SEARCH_KEY } from '@/constant';

const { Title } = Typography;

/**
 * 问卷列表页面组件
 * 实现了问卷列表的展示、搜索、分页加载等功能
 */
const List: FC = () => {
  // 当前页码状态
  const [page, setPage] = useState(1);
  // 问卷列表数据状态
  const [list, setList] = useState([]);
  // 问卷总数量状态
  const [total, setTotal] = useState(0);
  // 是否开始加载数据状态
  const [started, setStarted] = useState(false);
  // 判断是否还有更多数据
  const haveMoreData = total > list.length;
  // 获取URL搜索参数
  const [searchParams] = useSearchParams();
  // 搜索关键词
  const keyword = searchParams.get(LIST_SEARCH_KEY) || '';

  /**
   * 当搜索关键词变化时，重置分页相关状态
   * 确保从第一页开始重新加载数据
   */
  useEffect(() => {
    setStarted(false);
    setPage(1);
    setList([]);
    setTotal(0);
  }, [keyword]);

  /**
   * 加载问卷列表数据的函数
   * 使用useRequest进行异步请求管理
   */
  const { run: load, loading } = useRequest(
    async () => {
      const data = await getAllQuestionList({
        page,
        pageSize: LIST_PAGE_SIZE,
        keyword,
      });
      return data;
    },
    {
      manual: true, // 手动触发请求
      onSuccess: (result) => {
        // 请求成功后的处理
        const { list: l = [], total = 0 } = result;
        setList(list.concat(l)); // 将新数据追加到列表中
        setTotal(total); // 设置总数据量
        setPage(page + 1); // 页码递增
      },
    }
  );

  // 用于无限滚动加载的容器引用
  const containerRef = useRef<HTMLDivElement>(null);

  /**
   * 尝试加载更多数据的防抖函数
   * 防止滚动事件触发过于频繁
   */
  const { run: tryLoadMore } = useDebounceFn(
    () => {
      const elem = containerRef.current;
      if (elem === null) return;
      const domRect = elem.getBoundingClientRect();
      if (domRect === null) return;
      const { bottom } = domRect;
      // 当容器底部出现在视窗内时触发加载
      if (bottom <= document.documentElement.clientHeight) {
        load();
        setStarted(true);
      }
    },
    {
      wait: 500, // 防抖延迟500ms
    }
  );

  /**
   * 组件初始化和搜索参数变化时触发加载
   */
  useEffect(() => {
    tryLoadMore();
  }, [searchParams, tryLoadMore]);

  /**
   * 监听滚动事件实现无限滚动加载
   * 当还有更多数据时才添加滚动监听器
   */
  useEffect(() => {
    if (haveMoreData) {
      window.addEventListener('scroll', tryLoadMore);
    }
    return () => {
      // 组件卸载时移除事件监听器
      window.removeEventListener('scroll', tryLoadMore);
    };
  }, [searchParams, haveMoreData, tryLoadMore]);

  /**
   * 加载更多内容的展示组件
   * 根据不同状态显示不同内容
   */
  const LoadMoreContentElem = useMemo(() => {
    if (!started || loading) return <Spin />; // 显示加载中状态
    if (total === 0) return <Empty description="暂无数据" />; // 显示空数据状态
    if (!haveMoreData)
      return <div style={{ textAlign: 'center' }}>没有更多数据了</div>; // 显示没有更多数据状态
    return <span>开始加载下一页</span>; // 显示加载下一页提示
  }, [started, loading, total, haveMoreData]);

  return (
    <>
      {/* 页面头部：标题和搜索框 */}
      <div className={styles.header}>
        <div className={styles.left}>
          <Title level={3}>我的问卷</Title>
        </div>
        <div className={styles.right}>
          <QuestionSearch />
        </div>
      </div>

      {/* 页面内容：问卷卡片列表 */}
      <div className={styles.content}>
        {list.length > 0 &&
          list.map((q: any) => {
            return <QuestionCard key={q._id} {...q} />;
          })}
      </div>

      {/* 页面底部：加载更多内容 */}
      <div className={styles.footer}>
        <div ref={containerRef}>{LoadMoreContentElem}</div>
      </div>
    </>
  );
};

export default List;